package com.zhentao.device.dome;

import com.zhentao.pojo.WaterQualityData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.*;

@Service
public class WaterQualityMonitor {
    // ESP8266模块的连接信息
    private static final String SERVER_IP = "192.168.4.1";
    private static final int SERVER_PORT = 8080;
    private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间，单位毫秒
    private static final int BUFFER_SIZE = 1024;
    private static volatile boolean running = true;

    // 存储最新水质数据
    private static String latestPH = "N/A";
    private static String latestTemp = "N/A";
    private static String latestTurbidity = "N/A";
    private static long lastUpdateTime = 0;
    private static final int GROUP_TIMEOUT = 1500; // 1.5秒超时
    private static RedisTemplate redisTemplate;
    
    // 设备ID管理
    private static String currentDeviceId = "ESP8266_001"; // 默认设备ID
    private static final Map<String, String> deviceIdMap = new HashMap<>(); // 设备IP到ID的映射
    
    // 连接状态管理
    private static Socket deviceSocket = null;
    private static InputStream inputStream = null;
    private static boolean isConnected = false;

    /**
     * 初始化设备连接
     * @return 连接是否成功
     */
    public static boolean initializeConnection() {
        try {
            // 如果已经连接，先关闭旧连接
            if (isConnected && deviceSocket != null) {
                closeConnection();
            }
            
            System.out.println("正在连接到水质监测设备...");
            deviceSocket = new Socket();
            deviceSocket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), CONNECTION_TIMEOUT);
            deviceSocket.setSoTimeout(5000); // 设置读取超时时间到5秒
            
            inputStream = deviceSocket.getInputStream();
            isConnected = true;
            
            System.out.println("已成功连接到设备: " + SERVER_IP + ":" + SERVER_PORT);
            return true;
            
        } catch (IOException e) {
            System.err.println("连接设备失败: " + e.getMessage());
            e.printStackTrace();
            isConnected = false;
            deviceSocket = null;
            inputStream = null;
            return false;
        }
    }

    /**
     * 关闭设备连接
     */
    public static void closeConnection() {
        try {
            if (inputStream != null) {
                inputStream.close();
                inputStream = null;
            }
            if (deviceSocket != null && !deviceSocket.isClosed()) {
                deviceSocket.close();
                deviceSocket = null;
            }
            isConnected = false;
            System.out.println("设备连接已关闭");
        } catch (IOException e) {
            System.err.println("关闭连接时发生错误: " + e.getMessage());
        }
    }

    /**
     * 检查连接状态
     * @return 是否已连接
     */
    public static boolean isDeviceConnected() {
        return isConnected && deviceSocket != null && !deviceSocket.isClosed();
    }
    
    /**
     * 设置当前设备ID
     * @param deviceId 设备ID
     */
    public static void setCurrentDeviceId(String deviceId) {
        currentDeviceId = deviceId;
        System.out.println("设备ID已设置为: " + deviceId);
    }
    
    /**
     * 获取当前设备ID
     * @return 当前设备ID
     */
    public static String getCurrentDeviceId() {
        return currentDeviceId;
    }
    
    /**
     * 根据设备IP设置设备ID
     * @param deviceIp 设备IP地址
     * @param deviceId 设备ID
     */
    public static void setDeviceIdByIp(String deviceIp, String deviceId) {
        deviceIdMap.put(deviceIp, deviceId);
        System.out.println("设备IP " + deviceIp + " 映射到设备ID: " + deviceId);
    }
    
    /**
     * 根据设备IP获取设备ID
     * @param deviceIp 设备IP地址
     * @return 设备ID，如果未找到则返回默认ID
     */
    public static String getDeviceIdByIp(String deviceIp) {
        return deviceIdMap.getOrDefault(deviceIp, "ESP8266_" + deviceIp.replace(".", "_"));
    }

    /**
     * 获取水质数据
     * @return WaterQualityData 水质数据对象
     */
    public static WaterQualityData DeviceStatus() {
        WaterQualityData waterQualityData = new WaterQualityData();

        // 检查连接状态
        if (!isDeviceConnected()) {
            System.err.println("设备未连接，请先调用 initializeConnection() 方法");
            return createDefaultData();
        }

        try {
            // 数据缓冲区
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            byte[] data = new byte[BUFFER_SIZE];

            // 重置数据
            latestPH = "N/A";
            latestTemp = "N/A";
            latestTurbidity = "N/A";
            lastUpdateTime = 0;

            // 设置读取超时时间
            long startTime = System.currentTimeMillis();
            long timeout = 10000; // 10秒超时

            // 持续读取数据直到获取到完整数据或超时
            while (System.currentTimeMillis() - startTime < timeout) {
                try {
                    int bytesRead = inputStream.read(data);
                    if (bytesRead == -1) {
                        // 流结束
                        System.out.println("设备关闭连接");
                        isConnected = false;
                        break;
                    }

                    // 将数据添加到缓冲区
                    buffer.write(data, 0, bytesRead);

                    // 处理缓冲区中的完整数据行
                    byte[] rawBytes = buffer.toByteArray();
                    int lineEndIndex = findLineEndIndex(rawBytes);
                    while (lineEndIndex != -1) {
                        // 提取一行数据
                        byte[] lineBytes = new byte[lineEndIndex];
                        System.arraycopy(rawBytes, 0, lineBytes, 0, lineEndIndex);

                        // 处理这一行数据
                        processLine(lineBytes);

                        // 移除已处理的数据
                        byte[] remaining = new byte[rawBytes.length - lineEndIndex - 1];
                        System.arraycopy(rawBytes, lineEndIndex + 1, remaining, 0, remaining.length);
                        buffer.reset();
                        buffer.write(remaining);
                        rawBytes = buffer.toByteArray();

                        // 检查下一行
                        lineEndIndex = findLineEndIndex(rawBytes);
                    }

                    // 检查是否已获取到完整的水质数据
                    if (!"N/A".equals(latestPH) && !"N/A".equals(latestTemp) && !"N/A".equals(latestTurbidity)) {
                        System.out.println("已获取到完整的水质数据");
                        break;
                    }

                } catch (SocketTimeoutException e) {
                    // 读取超时，继续尝试
                    System.out.println("读取数据超时，继续等待...");
                } catch (IOException e) {
                    System.err.println("读取数据时发生错误: " + e.getMessage());
                    isConnected = false;
                    break;
                }
            }

            // 设置返回的水质数据对象
            waterQualityData.setPhValue(latestPH);
            waterQualityData.setTemperature(latestTemp);
            waterQualityData.setTurbidity(latestTurbidity);
            waterQualityData.setCollectTime(new Date());
            waterQualityData.setDeviceId(currentDeviceId); // 使用当前设备ID
            waterQualityData.setDataQuality("N/A".equals(latestPH) || "N/A".equals(latestTemp) || "N/A".equals(latestTurbidity) ? 2 : 1);
            waterQualityData.setCreateTime(new Date());

            System.out.println("水质数据采集完成: PH=" + latestPH + ", 温度=" + latestTemp + "℃, 浊度=" + latestTurbidity + "NTU");

        } catch (Exception e) {
            System.err.println("获取数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            isConnected = false;
            waterQualityData = createDefaultData();
        }

        return waterQualityData;
    }

    /**
     * 创建默认数据对象
     * @return 默认的水质数据对象
     */
    private static WaterQualityData createDefaultData() {
        WaterQualityData waterQualityData = new WaterQualityData();
        waterQualityData.setPhValue("N/A");
        waterQualityData.setTemperature("N/A");
        waterQualityData.setTurbidity("N/A");
        waterQualityData.setCollectTime(new Date());
        waterQualityData.setDeviceId(currentDeviceId); // 使用当前设备ID
        waterQualityData.setDataQuality(2); // 数据质量异常
        waterQualityData.setCreateTime(new Date());
        return waterQualityData;
    }

    // 查找换行符位置
    private static int findLineEndIndex(byte[] data) {
        for (int i = 0; i < data.length; i++) {
            if (data[i] == '\n') {
                return i;
            }
        }
        return -1;
    }

    // 处理单行数据
    private static void processLine(byte[] rawBytes) {
        try {
            // 使用GBK解码数据
            String decodedData = new String(rawBytes, "GBK");

            // 解析PH值
            if (decodedData.contains("PH:") || decodedData.contains("pH:")) {
                latestPH = parseValue(decodedData, "PH:\\s*([\\d.]+)");
                lastUpdateTime = System.currentTimeMillis();
            }
            // 解析温度值
            else if (decodedData.contains("温度:") || decodedData.contains("\\xce\\xc2\\xb6\\xc8")) {
                latestTemp = parseValue(decodedData, "温度:\\s*([\\d.]+)℃");
                lastUpdateTime = System.currentTimeMillis();
            }
            // 解析浊度值
            else if (decodedData.contains("浊度:") || decodedData.contains("\\xd7\\xc7\\xb6\\xc8")) {
                latestTurbidity = parseValue(decodedData, "浊度:\\s*([\\d.]+)NTU");
                lastUpdateTime = System.currentTimeMillis();
            }

        } catch (UnsupportedEncodingException e) {
            System.err.println("解码失败: " + e.getMessage());
        }
    }


    // 使用正则表达式提取数值
    private static String parseValue(String data, String patternStr) {
        try {
            Pattern pattern = Pattern.compile(patternStr);
            Matcher matcher = pattern.matcher(data);
            if (matcher.find()) {
                return matcher.group(1);
            }
        } catch (Exception e) {
            System.err.println("解析错误: " + e.getMessage());
        }
        return "N/A";
    }
}